(function(angular) {
	"use strict";
	angular.module("fs.waf").factory("setlDetailService", setlDetailService);
	setlDetailService.$inject = [ "$injector", "ajaxServiceFactory", "formatService", "arithService", "$filter", "clsConstants", "setlDetailFxRateService", "setlDetailStyleService", "fxCrossRateService" ];
	function setlDetailService($injector, ajaxServiceFactory, formatService, arithService, $filter, clsConstants, setlDetailFxRateService, setlDetailStyleService, fxCrossRateService) {
		var ajaxService = ajaxServiceFactory.buildAjaxService({
			getFeeCal : {
				url : "do/cls/settlement/settlementFeeCal",
				method : "post"
			}
		}), getSetlIndex = (function() {
			var index = 0;
			return (function() {
				return index++;
			});
		})(), payDetailService = function() {
			return $injector.get("payDetailService");
		}, setlDetailEventService = function() {
			return $injector.get("setlDetailEventService");
		}, settlementInitFactory = function() {
			return $injector.get("settlementInitFactory");
		};

		function initSetlDetails(settlement) {
			var paydetailSeqs = [];
			settlement.setlDetailCache = {};
			sortSetlDetails(settlement.setlDetails);
			angular.forEach(settlement.setlDetails, function(setlDetail, index, array) {
				paydetailSeqs[index] = setlDetail.paydetailSeq;
			});
			angular.forEach(settlement.setlDetails, function(setlDetail, index, array) {
				setlDetail.setlIndex = getSetlIndex();
				settlement.setlDetailCache["sd" + setlDetail.setlIndex] = setlDetail;
				initSettlementDetails(setlDetail, settlement);
				initializeSetlPayIdData(setlDetail);
				if ((!paydetailSeqs[index] || paydetailSeqs[index] == 0) && setlDetail.itemSubtype != clsConstants.SetlDetailItemSubType.INTEREST_NO_REFUND && setlDetail.itemHoldFlag != "Y"
						&& setlDetail.itemWaiveFlag != "Y" && setlDetail.itemCarryoverFlag != "Y" && setlDetail.itemTransferFlag != "Y") {
					setlDetailAddAmt(settlement, setlDetail, "B");
				}
				settlementInitFactory().getFunction(settlement.settlementInfo, "initSettlementData")(setlDetail, settlement);
			});
		}
		
		function sortSetlDetails(setlDetails){
			if(setlDetails && setlDetails.length > 0){
				for(var i = 0; i < setlDetails.length; i++){
					if(setlDetails[i].itemType == "P"){
						setlDetails.unshift(setlDetails[i]);
						setlDetails.splice(i+1, 1);
						break;
					}
				}
			}
		}

		/**
		 * 1. update setldetail"s paydetailSeq dropdown 2. if the setldetail not
		 * find paydetailSeq, need to add paydetail item
		 * 
		 * @param status:
		 *            load - load page; allocChange - settlement detail item"s
		 *            allocation code changed; payCcyChange - settlement detail
		 *            item"s pay ccy changed; change - other change
		 * 
		 */
		function updatePaydetailSeqForSetlDetail(settlement, setlDetail, status) {
			// ============== added by Steven Hu on 2006.4.17 begin
			var transfer = setlDetail.itemTransferFlag;
			var isTransfer = false;
			if (transfer) {
				if (transfer == "Y")
					isTransfer = true;
			}
			var isAddPayDetail = (setlDetail.itemType == "I" && settlement.deductIntAndFeeFlag.deductIntFlag == "N") || (setlDetail.itemType == "F" && settlement.deductIntAndFeeFlag.deductFeeFlag == "N");
			setlDetail.paydetailSeqOptions = [];
			if(settlement.payDetails != null){
				for(var i = 0; i < settlement.payDetails.length; i++){
					var payDetail = settlement.payDetails[i];
					if (payDetail.itemType != "D" && payDetail.itemSubtype != clsConstants.PayDetailItemSubType.DISCREPANCY && 
							payDetail.payCcy == setlDetail.payCcy && payDetail.allocCode == setlDetail.allocCode
							 && !(isAddPayDetail && payDetail.itemType == "P")
							 && (payDetail.itemSubtype == clsConstants.PayDetailItemSubType.ROLLOVER && setlDetail.itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER
									 || (payDetail.itemSubtype != clsConstants.PayDetailItemSubType.ROLLOVER && setlDetail.itemSubtype != clsConstants.SetlDetailItemSubType.ROLLOVER))
							 ) {
						setlDetail.paydetailSeqOptions.push({
							"value" : payDetail.payItemSeq,
							"label" : payDetail.payItemSeq
						});
					}
				}
			}
			if (setlDetail.paydetailSeqOptions.length == 0) {
				var waive = setlDetail.itemWaiveFlag;
				var hold = setlDetail.itemHoldFlag;
				var uItemWaiveValue = setlDetail.uItemWaive;
				if (setlDetail.itemSubtype != clsConstants.SetlDetailItemSubType.INTEREST_NO_REFUND) {
					var isAddPayMethod = true;
					if (uItemWaiveValue == "Y" && waive == "Y")
						isAddPayMethod = false;
					if (hold == "Y")
						isAddPayMethod = false;
					if (isAddPayMethod) {
						payDetailService().addPayDetailRow(settlement, setlDetail, isTransfer, false);
						return;
					}
				}
			}
			// check if the old value is in new options
			var curVal = setlDetail.paydetailSeq;// dropdown
			var isIn = false;// true - in
			if (curVal && curVal != "") {
				for (var i = 0; i < setlDetail.paydetailSeqOptions.length; i++) {
					if (curVal == setlDetail.paydetailSeqOptions[i].value) {
						isIn = true;
						break;
					}
				}
			}
			if (isTransfer) {
				if (setlDetail.paydetailSeqOptions.length > 1) {
					setlDetail.paydetailSeqOptions.splice(0, setlDetail.paydetailSeqOptions.length - 1);
				}
			} else {
				if (isIn)
					setlDetail.paydetailSeq = curVal;
				else {
					if (setlDetail.paydetailSeqOptions.length == 0) {
						setlDetail.paydetailSeq = "";
					} else {
						setlDetail.paydetailSeq = setlDetail.paydetailSeqOptions[0].value;
					}
				}
			}
			if(setlDetail.paydetailSeq && setlDetail.paydetailSeq != 0){
				var paydetail = payDetailService().getPayDetailByPayId(setlDetail.paydetailSeq, settlement);
				if(paydetail){
					paydetail.splitPayDetail_Show = payDetailService().isShowSplitPayDetail(settlement, paydetail);
				}
			}
		}

		/***********************************************************************
		 * Initialize the settlement detail item"s fx rateTypes, fx rates
		 * paymethod drop downs in the SETTLEMENT DETAILS TABLE initialize the
		 * item fields based on the current item currency and pay currency
		 * itemNo - the index of child item in settlement details array
		 * 
		 * itemccy == payccy: itemccy != payccy && itemccy == bccy; itemccy !=
		 * payccy && payccy == bccy; itemccy != payccy && payccy !=bccy &&
		 * itemccy != bccy;
		 **********************************************************************/
		function initSettlementDetails(setlDetail, settlement) {
			var itemType = setlDetail.itemType, childFlag = setlDetail.childFlag, translate = $filter("translate");
			if (itemType == null)
				return;
			if (itemType == "I") {
				setlDetail.itemDesc = translate("label.settlement.init." + itemType.toLowerCase()) + " " + formatService.formatDate(setlDetail.intDateFrom, "date") + " - "
						+ formatService.formatDate(setlDetail.intDateTo, "date");
			} else if (itemType == "F") {
				setlDetail.itemDesc = translate("label.settlement.init." + itemType.toLowerCase()) + " " + $filter("encode")(setlDetail.itemCode).substr(7);
			} else {
				setlDetail.itemDesc = translate("label.settlement.init." + itemType.toLowerCase());
			}
			if ((childFlag == "N") || (childFlag == "Y" && itemType == "P")) {
				// init setldetail fxrate / fxcrossrateflag /tax display
				setlDetailFxRateService.initSettlementDetailRateAndTax(settlement, setlDetail);
				// update payid options
				// 2006.3.15 if dicided to be changed by U_PAYDETAIL_SEQ
				updatePaydetailSeqForSetlDetail(settlement, setlDetail, "load");
				// 2006.7.14 disable/able split icon
			} else {
				var parentSetlDetail = null;
				for (var i = 0; i < settlement.setlDetails.length; i++) {
					var data = settlement.setlDetails[i];
					if (data.setlItemSeq == setlDetail.parentItemSeq) {
						parentSetlDetail = data;
						break;
					}
				}
				// child fxrate/ payamt/ payid
				initSettlementDetailsChildItem(settlement, setlDetail, parentSetlDetail);
			}
		}

		/***********************************************************************
		 * Initialize the child item"s payAmt, fx rateTypes, fx rates paymethod
		 * drop downs in the SETTLEMENT DETAILS TABLE initialize the item fields
		 * based on the parent item"s setting itemNo - the index of child item
		 * in settlement details array parentIndex - the index of parent item in
		 * settlement details array
		 **********************************************************************/
		function initSettlementDetailsChildItem(settlement, childSetlDetail, parentSetlDetail) {
			if (!childSetlDetail.itemType || childSetlDetail.itemType == "")
				return;
			// set this child"s payAmt and fxRate same as its parent
			setChildAmtAndRateByParent(childSetlDetail, parentSetlDetail, settlement.site);
			// set parent"s paymethod to this child"s
			setChildPaymethodByParent(childSetlDetail, parentSetlDetail);
		}

		/***********************************************************************
		 * set this child"s paymethod same as its parent childIndex - the index
		 * of child item in settlement details array parentIndex - the index of
		 * parent item in settlement details array
		 **********************************************************************/
		function setChildPaymethodByParent(childSetlDetail, parentSetlDetail) {
			var childPaymethod = childSetlDetail.paydetailSeq;
			if (childSetlDetail.paydetailSeqOptions) {
				childSetlDetail.paydetailSeqOptions = [];
			}
			if (parentSetlDetail && parentSetlDetail.paydetailSeqOptions) {
				childSetlDetail.paydetailSeqOptions.push(parentSetlDetail.paydetailSeqOptions);
			}
			if (childPaymethod == 0) {
				childSetlDetail.paydetailSeq = parentSetlDetail.paydetailSeq;
			} else {
				var curVal = childSetlDetail.paydetailSeq;
				var isIn = false;// true - in
				if (curVal && curVal != "") {
					for (var i = 0; i < childSetlDetail.paydetailSeqOptions.length; i++) {
						if (curVal == childSetlDetail.paydetailSeqOptions[i].value) {
							isIn = true;
							break;
						}
					}
				}
				if (!isIn) {
					if (childSetlDetail.paydetailSeqOptions.length == 0) {
						childSetlDetail.paydetailSeq = "";
					} else {
						childSetlDetail.paydetailSeq = childSetlDetail.paydetailSeqOptions[0].value;
					}
				}
			}
		}

		/**
		 * amt: the amount to be set withItemAmt: a string indicating if set
		 * value to itemAmt field. it can be empty. set amount to the
		 * itemAmtSetled of settlement details
		 */
		function setSetlDetailItemAmtSetled(setlDetail, amt, withItemAmt) {
			amt = formatService.parseNumber(amt + "");
			// set the value to itemAmt hidden filed
			setlDetail.itemAmtSettled = amt;
			// added on 2006.9.12
			if (withItemAmt) {
				setlDetail.itemAmt = amt;
			}
		}

		/***********************************************************************
		 * refresh all settlement detail items" Pay ID drop down after new
		 * payment detail item added edited by Steven Hu on 2006.3.15
		 **********************************************************************/
		function refreshPayMethods(settlement) {
			angular.forEach(settlement.setlDetails, function(data, index, array) {
				if (data.itemType) {
					if (!isRolloverRemittance(data.itemSubtype))
						updatePaydetailSeqForSetlDetail(settlement, data, "load");
					if(data.itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER){
						updatePaydetailSeqForSetlDetail(settlement, data, "load");
					}
				}
			});
		}
		
		function isRolloverRemittance(itemSubtype) {
			if (itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER || itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER_PASTDUE_INTEREST
					|| itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER_PD_PENALTY_INT || itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER_IR_PD_INT
					|| itemSubtype == clsConstants.SetlDetailItemSubType.ROLLOVER_IR_PD_PENALTY_INT) {
				return true;
			} else {
				return false;
			}
		}

		// calculate pay amount for settlement detail.
		// return a amount.
		// setlDetail: array index of settlementDetails
		// itemAmtFlag: it can be not provided. if exist then value only is "itemAmt"
		function calculatePayAmt(site, setlDetail, itemAmtFlag) {
			var itemccy = setlDetail.itemCcy;
			var itemamt = setlDetail.itemAmtSettled;
			if (itemAmtFlag && itemAmtFlag == "itemAmt")
				itemamt = setlDetail.itemAmt;
			var payccy = setlDetail.payCcy;
			var fxRate = setlDetail.fxRate;
			var fxRate2 = setlDetail.fxRate2;
			var fxr1 = 0;
			var fxr2 = 0;
			if (fxRate) {
				fxr1 = arithService.calc(fxRate, 0, "-");
			}
			if (fxRate2) {
				fxr2 = arithService.calc(fxRate2, 0, "-");
			}
			var baseCcy = site.baseCcy;
			var fxMulflag = site.isFxMultiply;
			var payamt = 0;
			var tmpamt = 0;
			// 2016-9-9 in case cross rate
			if (itemccy == baseCcy) {
				payamt = fxCrossRateService.FxCrossRate_Util.calculateRawPayAmt(setlDetail, fxMulflag == "Y" ? "N" : "Y", itemamt);
			} else {
				payamt = fxCrossRateService.FxCrossRate_Util.calculateRawPayAmt(setlDetail, fxMulflag, itemamt);
			}
			if (payamt) {
				return payamt;
			}
			if (itemccy == payccy) {// No rate
				payamt = itemamt;
				return payamt;
			} else {
				if (itemccy != baseCcy && payccy != baseCcy) {
					if (arithService.eq(fxr1, 0) || arithService.eq(fxr2, 0)) {
						return 0;
					}
					tmpamt = (fxMulflag == "Y") ? arithService.calc(arithService.calc(itemamt, fxr2, "*"), fxr1, "/") : arithService.calc(arithService.calc(itemamt, fxr2, "/"), fxr1, "*");
				}
				if (itemccy != baseCcy && payccy == baseCcy) {
					if (arithService.eq(fxr2, 0)) {
						return 0;
					}
					tmpamt = (fxMulflag == "Y") ? arithService.calc(itemamt, fxr2, "*") : arithService.calc(itemamt, fxr2, "/");
				}
				if (payccy != baseCcy && itemccy == baseCcy) {
					if (arithService.eq(fxr1, 0)) {
						return 0;
					}
					tmpamt = (fxMulflag == "Y") ? arithService.calc(itemamt, fxr1, "/") : arithService.calc(itemamt, fxr1, "*");
				}
			}
			payamt = tmpamt;
			return payamt;
		}

		/***********************************************************************
		 * construct the settlement pay id object for assigned settlement detail
		 * entry setldetailIndex: the index of settlement details
		 **********************************************************************/
		function initializeSetlPayIdData(setlDetail) {
			setlDetail.payIdB = setlDetail.paydetailSeq;
			setlDetail.payIdA = setlDetail.paydetailSeq;
			setlDetail.payAmtA = setlDetail.payAmt;
			setlDetail.payAmtB = setlDetail.payAmt;
		}

		/***********************************************************************
		 * the concrete function: delete the amount from the assigned payment
		 * detail entry type - the type: B or A
		 **********************************************************************/
		function setlDetailDeleteAmt(settlement, setlDetail, type) {
			var payItemSeq = setlDetail.payIdB;
			var amt = setlDetail.payAmtB;
			if (type == "A") {
				payItemSeq = setlDetail.payIdA;
				amt = setlDetail.payAmtA;
			}
			amt = formatService.parseNumber(amt);
			if (amt && amt != 0 && payItemSeq && (payItemSeq - 0) != 0) {
				var oldPaydetail = payDetailService().getPayDetailByPayId(payItemSeq, settlement);
				var payCrDr = oldPaydetail.crDrFlag;
				var oldAmountTextPureVal = oldPaydetail.payAmt;
				if (!oldAmountTextPureVal) {
					oldAmountTextPureVal = 0;
				}
				oldAmountTextPureVal = formatService.parseNumber(oldAmountTextPureVal);
				if (payCrDr == setlDetail.crDrFlag)
					oldAmountTextPureVal = arithService.calc(oldAmountTextPureVal, amt, "-");
				else
					oldAmountTextPureVal = arithService.calc(oldAmountTextPureVal, amt, "+");
				// change direction
				if (arithService.lt(oldAmountTextPureVal, 0)) {
					oldAmountTextPureVal = -oldAmountTextPureVal;
					if (oldPaydetail.crDrFlag == "C") {
						oldPaydetail.crDrFlag = "D";
					} else {
						oldPaydetail.crDrFlag = "C";
					}
					payDetailService().dynamicChangeThePayCodeList(oldPaydetail, settlement);
				}
				oldPaydetail.payAmt = oldAmountTextPureVal;
			}
		}

		/***********************************************************************
		 * the concrete function: add the amount to the assigned payment detail
		 * entry type - the type: B or A
		 **********************************************************************/
		function setlDetailAddAmt(settlement, setlDetail, type) {
			var payItemSeq = setlDetail.payIdB;
			var amt = setlDetail.payAmtB;
			if (type == "A") {
				payItemSeq = setlDetail.payIdA;
				amt = setlDetail.payAmtA;
			}
			amt = formatService.parseNumber(amt);
			if (amt && amt != 0 && payItemSeq && (payItemSeq - 0) != 0) {
				var newPaydetail = payDetailService().getPayDetailByPayId(payItemSeq, settlement);
				var newAmountTextPureVal = newPaydetail.payAmt;
				if (!newAmountTextPureVal) {
					newAmountTextPureVal = 0;
				}
				newAmountTextPureVal = formatService.parseNumber(newAmountTextPureVal);
				if (newPaydetail.crDrFlag == setlDetail.crDrFlag)
					newAmountTextPureVal = arithService.calc(newAmountTextPureVal, amt, "+");
				else
					newAmountTextPureVal = arithService.calc(newAmountTextPureVal, amt, "-");
				// change direction
				if (arithService.lt(newAmountTextPureVal, 0)) {
					newAmountTextPureVal = -newAmountTextPureVal;
					if (newPaydetail.crDrFlag == "C") {
						newPaydetail.crDrFlag = "D";
					} else {
						newPaydetail.crDrFlag = "C";
					}
					payDetailService().dynamicChangeThePayCodeList(newPaydetail, settlement);
				}
				newPaydetail.payAmt = newAmountTextPureVal;
			}
		}

		/***********************************************************************
		 * Add new item to pay or receive table in settlement details array
		 * action: split principal, add fee or refund fee spListIndex: F - add
		 * fee; S - split
		 **********************************************************************/
		function addSetlDetail(settlement, param, spListIndex) {
			var setlDetail = {};
			var maxIndex = getMaxIndexForSetlDetails(settlement.setlDetails);
			settlement.setlDetails.push(setlDetail);
			// use for set value to new row"s column"s childrens
			var feeTaxFlagTemp = param.feeTaxFlag;// true or false
			var itemDescTemp = param.itemDesc;
			// added on 2006.9.22 non-refund credit fee can be waived
			if (spListIndex == "F" && (!(param.crdr == "C" && param.childFlag == "N" && param.feeNewFlag == "Y" && param.feeId != null && param.feeId != ""))) {
				param.uItemWaive = "Y";
			}
			var parentItem = {}, intDateFromTemp, intDateToTemp;// only for
			// split
			if (spListIndex == "S") {// split
				parentItem = param.parentItem;
				intDateFromTemp = parentItem.intDateFrom;
				intDateToTemp = parentItem.intDateTo;
			} else {
				intDateFromTemp = "";
				intDateToTemp = "";
			}
			if (spListIndex == "F") {// only new fee can be deleted
				setlDetail.itemType = "F";
				setlDetail.feeNewFlag = "Y";
				setlDetail.itemSubtype = clsConstants.SetlDetailItemSubType.TXN_FEE;
			}
			setlDetail.itemType = param.itemType;
			if (setlDetail.itemType == "F" || setlDetail.itemType == "P")
				setlDetail.itemDesc = itemDescTemp;
			else if (setlDetail.itemType == "I") {
				setlDetail.itemDesc += parentItem.itemDesc;
			}
			setlDetail.itemCcy = param.itemCcy;
			setlDetail.itemAmt = param.itemAmt;
			setlDetail.itemAmtSettled = param.itemAmtSettled;
			setlDetail.itemCode = param.itemCode;
			setlDetail.setlItemSeq = maxIndex + 1;
			setlDetail.itemOrder = maxIndex + 1;
			setlDetail.feeNewFlag = param.feeNewFlag;
			setlDetail.feeId = param.feeId;
			setlDetail.crDrFlag = param.crdr;
			setlDetail.intDateFrom = intDateFromTemp;
			setlDetail.intDateTo = intDateToTemp;
			setlDetail.itemSubtype = param.itemSubtype;
			setlDetail.taxAmt = param.taxAmt;
			setlDetail.itemCarryoverFlag = param.carryFlag;
			setlDetail.itemTransferFlag = param.transferFlag;
			setlDetail.setlId = settlement.settlementInfo.setlId;
			setlDetail.siteCode = settlement.settlementInfo.siteCode;
			setlDetail.childFlag = param.childFlag;
			setlDetail.parentItemSeq = param.parentItemSeq;
			setlDetail.uItemWaive = param.uItemWaive;
			setlDetail.feeAmtOrg = param.feeAmtOrg;
			setlDetail.payCcy = param.payCcy;
			setlDetail.payAmt = param.payAmt;
			setlDetail.fxRateType = param.fxType;
			setlDetail.fxRate = param.fxRate;
			setlDetail.fxRate_Readonly = true;
			setlDetail.fxRate1CcyFrom = "";
			setlDetail.fxRateType2 = param.fxType2;
			setlDetail.fxRate2 = param.fxRate2;
			setlDetail.fxRate2_Readonly = true;
			setlDetail.fxRate2CcyFrom = "";
			setlDetail.taxWaiveFlag = param.taxWaiveFlag;
			setlDetail.fxCrossRateFlag = "N";
			if ((setlDetail.taxAmt - 0) != 0) {
				setlDetail.taxWaiveFlag_Show = true;
			} else {
				setlDetail.taxWaiveFlag_Show = false;
			}
			setlDetail.allocCode = param.allocCode;
			setlDetail.itemHoldFlag = param.holdFlag;
			setlDetail.itemWaiveFlag = param.waiveFlag;
			// TODO
			if (spListIndex == "F" && (setlDetail.crDrFlag == "D" || 
					!(setlDetail.crDrFlag == "C" && setlDetail.childFlag == "N" && setlDetail.feeNewFlag == "Y" && setlDetail.feeId != null && setlDetail.feeId != ""))) {
				setlDetail.itemHoldFlag_Show = true;
				setlDetail.itemWaiveFlag_Show = true;
			} else {// if((spListIndex == "S") || (spListIndex == "F" &&
				// setlDetail.crDrFlag == "C"))
				setlDetail.itemHoldFlag_Show = false;
				setlDetail.itemWaiveFlag_Show = false;
			}

			if ((spListIndex == "F" && setlDetail.itemType == "F" && isRolloverRemittance(setlDetail.itemSubtype))) {
				setlDetail.paydetailSeq_Readonly = true;
			} else {
				setlDetail.paydetailSeq_Readonly = false;
			}
			// set value to checkbox fileds
			var parentType = settlement.settlementInfo.parentType;
			if (parentType == "REPAY" && settlement.payment.finalPayment == "Y") {
				setlDetail.itemHoldFlag_Readonly = true;
			}
			if ((setlDetail.taxAmt - 0) != 0) {
				if (setlDetail.taxWaiveFlag == "Y") {
					setlDetail.taxWaiveFlag = "Y";
				}
			}
			// initial the new item
			if (spListIndex == "S") {
				if (setlDetail.itemType == "P") {
					initSettlementDetails(setlDetail, settlement);// init
																					// this
				} else {
					initSettlementDetailsChildItem(settlement, setlDetail, parentItem);// init
				}
			} else {
				initSettlementDetails(setlDetail, settlement);// init
																				// this
			}
			if (spListIndex == "F") {
				if (setlDetail.crDrFlag == "D" && setlDetail.payAmt == 0) {
					if (settlementInitFactory().getTxnService(settlement.settlementInfo).resetSetlDetailPayAmt) {
						settlementInitFactory().getTxnService(settlement.settlementInfo).resetSetlDetailPayAmt(settlement, setlDetail);
					} else {
						var amt = calculatePayAmt(settlement.site, setlDetail);
						setlDetail.payAmt = amt;
					}
				}
			}
			// 20060808 construct the settlement pay id object
			initializeSetlPayIdData(setlDetail);

			/*
			 * //20060815 add to pay priority list
			 * if(isControllPriority(settlement, setlDetail)){
			 * settlement.priorityList[setlDetail.itemOrder] = setlDetail;
			 * disableSplit(setlDetail, false); }
			 */
			// flash
			setlDetail.setlIndex = getSetlIndex();
			settlement.setlDetailCache["sd" + setlDetail.setlIndex] = setlDetail;
			setlDetail.setlDetailConfig = initSetlDetailConfig(settlement, setlDetail, settlement.layoutConfigCache);
			setlDetail.setlDetailConfig.gridConfigs.taxAmt.label = setlDetail.taxAmt_label;
			return setlDetail;
		}
		
		function getMaxIndexForSetlDetails(setlDetails){
			var resultIndex = 0;
			angular.forEach(setlDetails, function(data, index, array){
				if(data.setlItemSeq > resultIndex){
					resultIndex = data.setlItemSeq;
				}
			});
			return resultIndex;
		}
		
		function initSetlDetailConfig(settlement, item, layoutConfig){
			var dynaConfig = angular.copy(layoutConfig.formConfigs.setlDetailInfo);
			//1. pay Ccy
			dynaConfig.gridConfigs.payCcy.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".payCcy_Readonly";
			//2.fxRate
			dynaConfig.gridConfigs.fxRate.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate_Readonly";
			dynaConfig.gridConfigs.fxRate.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate_Show";
			dynaConfig.gridConfigs.fxRateType.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRateType_Readonly";
			dynaConfig.gridConfigs.fxRateType.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRateType_Show";
	
			dynaConfig.gridConfigs.fxRate2.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate2_Show";
			dynaConfig.gridConfigs.fxRate2.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate2_Readonly";
			dynaConfig.gridConfigs.fxRateType2.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRateType2_Readonly";
			dynaConfig.gridConfigs.fxRateType2.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRateType2_Show";
		
			dynaConfig.gridConfigs.fxRate1CcyFrom.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate1CcyFrom_Show";
			dynaConfig.gridConfigs.fxRate2CcyFrom.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxRate2CcyFrom_Show";
			//3.allocCode
			dynaConfig.gridConfigs.allocCode.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".allocCode_Readonly";
			dynaConfig.gridConfigs.allocCode.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".allocCode_Show";
			//4.paydetailSeq
			dynaConfig.gridConfigs.paydetailSeq.options.data = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".paydetailSeqOptions";
			dynaConfig.gridConfigs.paydetailSeq.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".paydetailSeq_Readonly";
			//5.fxCrossRat
			dynaConfig.gridConfigs.fxCrossRate.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRate_Readonly";
			dynaConfig.gridConfigs.fxContractNo.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxContractNo_Readonly";
			dynaConfig.gridConfigs.fxContractNo.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxContractNo_Show";
			dynaConfig.gridConfigs.fxCrossRate.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRate_Show";
			dynaConfig.gridConfigs.fxCrossRateCreateNew.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRateCreateNew_Show";
			dynaConfig.gridConfigs.fxCrossRateNote.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRateNote_Show";
			dynaConfig.gridConfigs.fxCrossRateFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRateFlag_Readonly";
			dynaConfig.gridConfigs.fxCrossRateFlag.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".fxCrossRateFlag_Show";
			//6.taxAmt
			dynaConfig.gridConfigs.taxAmt.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".taxAmt_Show";
			dynaConfig.gridConfigs.taxAmt.label = item.taxAmt_label || dynaConfig.gridConfigs.taxAmt.label;
			//7.holdFlag
			dynaConfig.gridConfigs.itemHoldFlag.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemHoldFlag_Show";
			dynaConfig.gridConfigs.itemHoldFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemHoldFlag_Readonly";
			//8. itemWaiveFlag
			dynaConfig.gridConfigs.itemWaiveFlag.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemWaiveFlag_Show";
			dynaConfig.gridConfigs.itemWaiveFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemWaiveFlag_Readonly";
			//9. itemtaxwaive
			dynaConfig.gridConfigs.taxWaiveFlag.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".taxWaiveFlag_Show";
			dynaConfig.gridConfigs.taxWaiveFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".taxWaiveFlag_Readonly";
			//10.ItemTransferFlag
			dynaConfig.gridConfigs.itemTransferFlag.show = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemTransferFlag_Show";
			dynaConfig.gridConfigs.itemTransferFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemTransferFlag_Readonly";
			//11.itemCarryFlag
			dynaConfig.gridConfigs.itemCarryoverFlag.readonly = "vm.settlement.setlDetailCache.sd" + item.setlIndex + ".itemCarryoverFlag_Readonly";
			setlDetailStyleService.initSetlDetailStyle(settlement, item);
			return dynaConfig;
		}
		
		function flashSetlDetailsConfig(settlement, layoutConfig){
			var setlDetails = settlement.setlDetails;
			if(setlDetails && setlDetails.length > 0){
				angular.forEach(setlDetails, function(data, index, array){
					data.setlDetailConfig = initSetlDetailConfig(settlement, data, layoutConfig);
				});
			}
		}

		function updateSetDetailByFee(settlement) {
			var setlDetails = settlement.setlDetails;
			var payDetails = settlement.payDetails;
			for (var i = 0; i < setlDetails.length; i++) {
				var setlDetail = setlDetails[i];
				if (setlDetail.itemSubtype == clsConstants.SetlDetailItemSubType.CHANNEL_FEE) {
					if (setlDetailEventService().deleteSetlDetail(settlement, setlDetail)) {
						i--;
					}
				}
			}
			angular.forEach(payDetails, function(payDetail, index, array) {
				if (payDetailService().isUpdateChannelFee(settlement, payDetail)) {
					addSetlDetailForChangedPayCode(settlement, payDetail);
				}
			});
		}

		function addSetlDetailForChangedPayCode(settlement, payDetail) {
			if (!payDetail.payCodeObj || !payDetail.payCodeObj.feeCode) {
				return;
			}
			var feeObj = getFeeObjParam(settlement);
			feeObj.feeCode = payDetail.payCodeObj.feeCode;
			// TODO doesn"t have to be all charged
			feeObj.txnAmt = payDetail.payAmt;
			if(!feeObj.loanId){
				delete feeObj.loanId;
			}
			ajaxService.getFeeCal({
				feeObj : feeObj
			}).then(function(response) {
				var settlement_result = response ? response.data : {};
				var feeObj = settlement_result.feeObj;
				var feeCode = feeObj.feeCode;
				var feeAmt = feeObj.feeAmt;
				var feeCcy = feeObj.feeCcy;
				if (feeCode != "" && (feeAmt - 0) != 0 && feeCcy != "") {
					var param = new Object();
					param.itemType = "F";
					param.crdr = feeObj.crDrFlag;
					param.itemCcy = feeCcy;
					param.itemAmt = feeAmt;
					param.payCcy = feeCcy;
					param.payAmt = feeAmt;
					param.allocCode = feeObj.allocCode;
					param.itemCode = feeCode;
					param.itemDesc = feeObj.feeDesc;
					param.itemSubtype = clsConstants.SetlDetailItemSubType.CHANNEL_FEE;
					param.fxType = "C";
					param.fxRate = 1.0;
					param.fxType2 = "C";
					param.fxRate2 = 1.0;
					if(settlementInitFactory().getTxnService(settlement.settlementInfo).getHoldFeeFlag){
						param.holdFlag = settlementInitFactory().getTxnService(settlement.settlementInfo).getHoldFeeFlag(settlement);
					}else{
						param.holdFlag = "N";
					}
					param.holdFlag = "Y";
					param.waiveFlag = "N";
					param.uItemWaive = "N";
					param.carryFlag = "N";
					param.transferFlag = "N";
					param.taxWaiveFlag = "N";
					param.childFlag = "N";
					param.feeNewFlag = "Y";
					param.feeId = "";
					param.feeTaxFlag = "N";
					param.taxAmt = 0;
					param.parentItemSeq = 0;
					param.payItemSeq = payDetail.payItemSeq;
					var target;
					if (param.crdr == "C") {
						target = "addcr";
					} else {
						target = "adddr";
					}
					feeboxCallback(settlement, param, target);
				}
			});
		}

		function feeboxCallback(settlement, param, target) {
			var parentType = settlement.settlementInfo.parentType;
			if (param != null) {
				// added on 2006.12.7 if feecode.alloccode is null
				if (param.allocCode == "" || param.allocCode == null || typeof param.allocCode == "undefined") {
					param.allocCode = "CUSTOMER";
					if (parentType == "REPAY") {
						var paymentTypeVal = settlement.payment.repayType;
						if (paymentTypeVal && (paymentTypeVal == "R" || paymentTypeVal == "W" || paymentTypeVal == "P"))
							param.allocCode = "OBLIGOR";
					}
				}
				param.itemAmtSettled = param.itemAmt;
				param.feeAmtOrg = arithService.calc(param.itemAmt, param.taxAmt, "-");
				// added on 2006.8.31 includeFee flag control
				if (target == "adddr") {
					var baseCcy = settlement.site.baseCcy;
					if (parentType == "REPAY" && param.allocCode == settlement.settlementInfo.principalAlloc) {
						var includeFeeVal = settlement.payment.feeInclude;
						var payCcyVal = settlement.payment.payCcy;
						if (payCcyVal == null || payCcyVal == "")
							payCcyVal = txnCcy;
						if (includeFeeVal == "Y" && param.payCcy != payCcyVal) {// new
							param.payCcy = payCcyVal;
							param.payAmt = 0;
							param.fxType = "B";
							param.fxRate = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "pay", baseCcy, payCcyVal);
							param.fxType2 = "S";
							param.fxRate2 = setlDetailFxRateService.getToBaseCcyFxRateValue("D", "item", baseCcy, param.itemCcy);
						}
					}
				}
				var setl = addSetlDetail(settlement, param, "F");
				if (settlementInitFactory().getTxnService(settlement.settlementInfo).feebox) {
					settlementInitFactory().getTxnService(settlement.settlementInfo).feebox(settlement, param, setl);
				} else {
					if (setl)
						setlDetailAddAmt(settlement, setl, "B");
				}
			}
		}

		/***********************************************************************
		 * set this child"s payAmt and fxRate same as its parent childSetlDetail -
		 * the index of child item in settlement details array parentSetlDetail -
		 * the index of parent item in settlement details array
		 **********************************************************************/
		function setChildAmtAndRateByParent(childSetlDetail, parentSetlDetail, site) {
			var itemccy = childSetlDetail.itemCcy, payccy = childSetlDetail.payCcy, bccy = site.baseCcy;
			if (payccy == itemccy) {
				childSetlDetail.payAmt = childSetlDetail.itemAmtSettled;
				setlDetailStyleService.disableFxRateAndFxRate2(setlDetail);
			} else {
				childSetlDetail.fxRateType = parentSetlDetail.fxRateType;
				childSetlDetail.fxRate = parentSetlDetail.fxRate;
				childSetlDetail.fxRateType2 = parentSetlDetail.fxRateType2;
				childSetlDetail.fxRate2 = parentSetlDetail.fxRate2;
				childSetlDetail.payAmt = calculatePayAmt(site, childSetlDetail);
				// display the fxrate ccy text
				childSetlDetail.fxRate1CcyFrom = "";
				childSetlDetail.fxRate2CcyFrom = "";
				if (payccy != bccy)
					childSetlDetail.fxRate1CcyFrom = payccy;
				if (itemccy != bccy)
					childSetlDetail.fxRate2CcyFrom = itemccy;
			}
		}

		function getFeeObjParam(settlement) {
			var loanId = 0;
			if (settlement.loan && settlement.loan.loanInfo) {
				loanId = settlement.loan.loanInfo.loanId;
			}
			var txnCcy = settlement.txnCcy;
			var parentType = settlement.settlementInfo.parentType;
			var effectiveDate = settlement.settlementInfo.effectiveDate;
			var prodCode = "";
			var prodType = "";
			var prodInfo = settlementInitFactory().getFunction(settlement.settlementInfo, "getProdCodeAndType")(settlement);
			if (prodInfo) {
				prodCode = prodInfo.prodCode;
				prodType = prodInfo.prodType;
			}
			var parentId = settlement.settlementInfo.parentId;
			var txnamt = settlementInitFactory().getFunction(settlement.settlementInfo, "getTxnAmount")(settlement);
			var assetId = settlementInitFactory().getFunction(settlement.settlementInfo, "getAssetId")(settlement);
			var hasAsset = "N";
			if (assetId > 0)
				hasAsset = "Y";

			return {
				"txnAmt" : txnamt,
				"txnCcy" : txnCcy,
				"loanId" : loanId,
				"hasAsset" : hasAsset,
				"effectiveDate" : effectiveDate,
				"parentId" : parentId,
				"parentType" : parentType,
				"prodCode" : prodCode,
				"prodType" : prodType
			};
		}

		function disableSplit(setlDetail, disable) {
			setlDetail.isShowSplit = disable;
		}

		/**
		 * basic util function: disable or enable its children" pay method,and
		 * update the relative amount in payment details only for
		 * changePaymethod, transfer functions setlDetail:array index of
		 * settlement detail items
		 */
		function changeChildPaymethod(settlement, setlDetail) {
			if (setlDetail) {
				var splitedSetlItemSeq = setlDetail.setlItemSeq;
				angular.forEach(settlement.setlDetails, function(data, index, array) {
					if ((data != null) && (data.parentItemSeq == splitedSetlItemSeq)) {
						setChildPaymethodByParent(data, setlDetail);
						// 20060807 update the payment detail relative amount
						payDetailService().changePaydetailBySetldetail(settlement, data);
					}
				});
			}
		}
		
		// Reset the fxRates of the assigned settlement detail entry and
		// recalculate the payAmt.
		// itemNo: array index of settlementDetails
		function resetFxRatesAmdPayAmt(settlement, setlDetail) {
			var itemccy = setlDetail.itemCcy;
			var payccy = setlDetail.payCcy;
			if (payccy == itemccy) {
				setlDetail.payAmt = setlDetail.itemAmtSettled;
				setlDetailStyleService.disableFxRateAndFxRate2(setlDetail);
				// 2016-9-9 disabled fxCrossRateFlag
				fxCrossRateService.FxCrossRate_Util.disableCrossRate(setlDetail);
			} else {
				fxCrossRateService.FxCrossRate_Util.enableCrossRate(setlDetail);
				// if it is not cross rate, we need the normal fx rate section,
				// the following behaviors are visible on page
				// if it is cross rate, the normal fx rate section is hidden, so
				// the following behaviors are invisible. so keeping them have
				// no side effects
				if (fxCrossRateService.FxCrossRate_Util.isCrossRate(setlDetail)) {
					setlDetailStyleService.disableFxRateAndFxRate2(setlDetail);
				} else {
					setlDetailFxRateService.assignDefaultValueToFxRateAndFxRate2(settlement, setlDetail);
					setlDetailFxRateService.enableFxRateAndFxRate2(setlDetail, settlement.site.baseCcy);
				}
				setlDetail.payAmt = calculatePayAmt(settlement.site, setlDetail);
			}
			setlDetailStyleService.fxCrossStyle(setlDetail);
		}

		return {
			addSetlDetail : addSetlDetail,
			calculatePayAmt : calculatePayAmt,
			changeChildPaymethod : changeChildPaymethod,
			disableSplit : disableSplit,
			feeboxCallback : feeboxCallback,
			flashSetlDetailsConfig : flashSetlDetailsConfig,
			getFeeObjParam : getFeeObjParam,
			initializeSetlPayIdData : initializeSetlPayIdData,
			initSetlDetails : initSetlDetails,
			initSettlementDetails : initSettlementDetails,
			initSettlementDetailsChildItem : initSettlementDetailsChildItem,
			isRolloverRemittance : isRolloverRemittance,
			refreshPayMethods : refreshPayMethods,
			resetFxRatesAmdPayAmt : resetFxRatesAmdPayAmt,
			setChildAmtAndRateByParent : setChildAmtAndRateByParent,
			setlDetailAddAmt : setlDetailAddAmt,
			setlDetailDeleteAmt : setlDetailDeleteAmt,
			setSetlDetailItemAmtSetled : setSetlDetailItemAmtSetled,
			updatePaydetailSeqForSetlDetail : updatePaydetailSeqForSetlDetail,
			updateSetDetailByFee : updateSetDetailByFee
		};
	}
})(angular);
